<template>
  <div class="pdf-main-canvas">
    <canvas ref="mainCanvas"></canvas>
    <div ref="annotationLayer" class="pdf-annotation-layer"></div>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, onBeforeUnmount, defineEmits } from "vue";
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist";

/**
 * 确保PDF.js Worker已配置
 * 如果主组件已配置则跳过，否则使用CDN配置
 * @author Ning,Li
 */
if (!GlobalWorkerOptions.workerSrc) {
  GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js`;
}

const emit = defineEmits(["rendered", "canvas"]);
const props = defineProps({
  src: String,
  page: Number,
  scale: {
    type: Number,
    default: 2.0,
  },
});

const mainCanvas = ref(null);
const annotationLayer = ref(null);
let pdfDoc = null;
let pageObj = null;
let renderTask = null;

/**
 * 渲染PDF页面
 * @author Ning,Li
 */
const renderPage = async () => {
  if (!props.src || !props.page) return;

  try {
    // 加载PDF文档
    if (!pdfDoc || pdfDoc.src !== props.src) {
      const loadingTask = getDocument(props.src);
      pdfDoc = await loadingTask.promise;
      pdfDoc.src = props.src; // 标记源文件
    }

    // 获取页面
    pageObj = await pdfDoc.getPage(props.page);

    const viewport = pageObj.getViewport({ scale: props.scale });

    const canvas = mainCanvas.value;
    const context = canvas.getContext("2d");

    // dpr 适配
    const dpr = window.devicePixelRatio || 1;
    canvas.width = viewport.width * dpr;
    canvas.height = viewport.height * dpr;
    canvas.style.width = `${viewport.width}px`;
    canvas.style.height = `${viewport.height}px`;

    context.setTransform(1, 0, 0, 1, 0, 0); // 先重置
    context.setTransform(dpr, 0, 0, dpr, 0, 0);

    renderTask = pageObj.render({ canvasContext: context, viewport });
    await renderTask.promise;

    // 手动渲染 annotationLayer（只处理链接类型）
    if (annotationLayer.value) {
      annotationLayer.value.innerHTML = "";
      const annotations = await pageObj.getAnnotations({ intent: "display" });
      annotations.forEach((ann) => {
        if (ann.subtype === "Link" && ann.url) {
          // ann.rect: [llx, lly, urx, ury]，以PDF坐标为基准
          const [llx, lly, urx, ury] = ann.rect;
          // PDF坐标左下为原点，需转换为HTML坐标
          const { transform, width, height } = viewport;
          // 计算左上角和宽高
          const x = Math.min(llx, urx);
          const y = Math.max(lly, ury);
          const w = Math.abs(urx - llx);
          const h = Math.abs(ury - lly);

          // 转换为屏幕坐标
          const [left, top] = viewport.convertToViewportPoint(x, y);
          const [right, bottom] = viewport.convertToViewportPoint(x + w, y - h);

          const a = document.createElement("a");
          a.href = ann.url;
          a.target = "_blank";
          a.style.position = "absolute";
          a.style.left = `${Math.min(left, right)}px`;
          a.style.top = `${Math.min(top, bottom)}px`;
          a.style.width = `${Math.abs(right - left)}px`;
          a.style.height = `${Math.abs(bottom - top)}px`;
          a.style.background = "rgba(0,0,0,0)";
          a.style.zIndex = "10";
          a.title = ann.url;
          annotationLayer.value.appendChild(a);
        }
      });
      annotationLayer.value.style.width = `${viewport.width}px`;
      annotationLayer.value.style.height = `${viewport.height}px`;
      annotationLayer.value.style.left = canvas.offsetLeft + "px";
      annotationLayer.value.style.top = canvas.offsetTop + "px";
    }

    emit("rendered", props.page); // 渲染完通知父组件
    emit("canvas", mainCanvas.value); // 渲染完后传递canvas
  } catch (error) {
    console.error("PDF加载失败:", error);
  }
};

let pdfLoading = false;
const loadPdf = async () => {
  if (!props.src) return;
  pdfLoading = true;
  try {
    // 卸载旧文档
    if (pdfDoc && pdfDoc.destroy) {
      await pdfDoc.destroy();
      pdfDoc = null;
    }
    await renderPage();
  } catch (error) {
    console.error("PDF加载失败:", error);
    pdfLoading = false;
  }
};

watch(() => props.src, loadPdf, {
  immediate: true,
});
watch(
  () => props.scale,
  () => {
    renderPage();
  }
);
watch(
  () => props.page,
  (newPage) => {
    renderPage();
  }
);

onMounted(() => {
  window.addEventListener("resize", () => renderPage());
});
onBeforeUnmount(() => {
  window.removeEventListener("resize", () => renderPage());
  if (mainCanvas.value) {
    mainCanvas.value.width = 0;
    mainCanvas.value.height = 0;
  }
  if (pageObj && pageObj.cleanup) {
    try {
      pageObj.cleanup();
    } catch (e) {}
    pageObj = null;
  }
  if (pdfDoc && pdfDoc.destroy) {
    pdfDoc.destroy();
  }
  pdfDoc = null;
});
</script>

<style scoped>
.pdf-annotation-layer {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: auto;
}
.pdf-main-canvas {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #222;
  margin: 10px 0;
  width: 100%;
  overflow: hidden;
}
canvas {
  display: block;
  max-width: 100%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  background: #fff;
}
</style>
